package network;

import guimessage.NotifNetwork;
import itdb1.commun.*;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import controller.GUIController;

public class DownloaderTCPClient extends TCPClient {

	private GUIController guicontroller;
	
	public DownloaderTCPClient(Socket sock) {
		super(sock);
		guicontroller = GUIController.getInstance();
	}

	@Override
	public void run() {
		
		FileDescription dscrpt = receiveFileDescription();
		guicontroller.writeDebugScreen("DownloaderTCPClient > file description received\n\t" + dscrpt.toString() + "\n");
		
		boolean answer = guicontroller.AskAcknowledgementDownload(dscrpt.getFromIp(), dscrpt);
		sendFileAnswer(answer);
		
		if(answer)
		{
			String directoryPath = LocalNetworkSettings.PATH_DOWNLOAD_DIRECTORY;
			
			if( receiveFile( directoryPath + dscrpt.getName(), (int) dscrpt.getSize() ) )
			{
				guicontroller.writeDebugScreen("DownloaderTCPClient > file received\n");
				guicontroller.messages.add(new NotifNetwork(sock.getInetAddress(), "Download succeeded"));
			}
			else
			{
				guicontroller.writeDebugScreen("DownloaderTCPClient > transfer failed\n");
				guicontroller.messages.add(new NotifNetwork(sock.getInetAddress(), "Download failed"));
			}
		}			
			
		closeConnection();
		guicontroller.writeDebugScreen("DownloaderTCPClient > socket closed\n");
	}

	private FileDescription receiveFileDescription()
	{
		FileDescription dscrpt = null;
		
		try
		{
			ObjectInputStream ins = new ObjectInputStream(sock.getInputStream());
			Object o = ins.readObject();
			dscrpt = (FileDescription) o ;
			dscrpt.setFromIp(sock.getInetAddress());
		}
		catch(IOException ioException)
		{
			ioException.printStackTrace();
		}
		catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}
		
		return dscrpt;
	}
	
	private boolean sendFileAnswer(boolean answer)
	{
		try{
			ObjectOutputStream outs = new ObjectOutputStream(sock.getOutputStream());
			
			outs.writeObject( new FileAnswer(answer) );
			outs.flush();
			
			return true;
		}
		catch(IOException ioException)
		{
			ioException.printStackTrace();
			return false;
		}
	}
	
	// à améliorer
	private boolean receiveFile(String path, int fileLength)
	{
		FileOutputStream downloadedFileStream = null;
		BufferedInputStream  bufferInSocket = null;
		
		try
		{
			downloadedFileStream = new FileOutputStream(new File(path));
			bufferInSocket = new BufferedInputStream(sock.getInputStream());
			
			
			// Il va falloir penser ici à faire une liaison avec le controleur de gui pour informer l'utilisateur de la progression
			int receivedBytes = 0;
			while(receivedBytes < fileLength)
			{
				byte[] buffer = new byte[1024];
				int b;
				
				b = bufferInSocket.read(buffer, 0, buffer.length);
				if(b > 0)
				{
					receivedBytes += b;
					downloadedFileStream.write(buffer);
				}
			}
		}
		catch(IOException ioException)
		{
			ioException.printStackTrace();
			return false;
		}
		finally
		{
			try
			{
				downloadedFileStream.close();
				bufferInSocket.close();
			}
			catch(IOException ioException)
			{
				ioException.printStackTrace();
			}
		}
		
		
		
		return true;
	}
	
	private void closeConnection()
	{
		if(sock != null)
		{
			try{
				sock.close();
			}
			catch(IOException ioException)
			{
				ioException.printStackTrace();
			}
		}
	}
}
